package solutions.ferpa.ztest.ent;

import java.sql.*;
import java.util.ArrayList;
import br.com.telescope.adsrt.dom.*;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.t2.exception.Severity;

/**
 * API de persistência de dados da entidade MENUS
 * @author Gerado pelo Telescope
 */
public class EntMenus extends Entity {
    
    public final static String ENTITY_NAME = "RTMENU.MENUS";
    public final static String TABLE_NAME = "MENUS";
    
    // <editor-fold defaultstate="collapsed" desc="Contrutores e inicializacao">
    /**
     * Construtores
     */
    public EntMenus() {
        super();
        initialize();
    }
    
    public EntMenus(BaseRuntime ctx) {
        super();
        initialize(ctx);
    }
    
    @Override
    public String getPrimaryKeyColumn() {
        return "ID";
    }
    
    @Override
    public void initialize(BaseRuntime ctx) {
        super.initialize(ctx);
        initialize();
    }
    
    public void initialize() {
        aId = new DomId(this,"ID", "Id"); 
        aId.setRequired(true);
        oId = new DomId();
        aMenu = new DomUpper(this,"MENU", "Menu"); 
        aMenu.setRequired(true);
        aMenu.setSize(80);
        oMenu = new DomUpper();
        aTitulo = new DomText(this,"TITULO", "Título"); 
        aTitulo.setRequired(true);
        aTitulo.setSize(160);
        oTitulo = new DomText();
        aDescricao = new DomTextLong(this,"DESCRICAO", "Descrição"); 
        oDescricao = new DomTextLong();
        aSequencia = new DomInteger(this,"SEQUENCIA", "Sequência"); 
        aSequencia.setDefaultValue("50");
        oSequencia = new DomInteger();
        aTopo = new DomFlag(this,"TOPO", "Topo"); 
        aTopo.setSize(1);
        aTopo.setDefaultValue("N");
        oTopo = new DomFlag();
        aSistemaId = new DomId(this,"SISTEMA_ID", "Sistema (DEPRECIADO)"); 
        oSistemaId = new DomId();
        ressetModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributos da entidade">
    
    // Id
    private DomId aId;
    private DomId oId;
    
    // Menu
    private DomUpper aMenu;
    private DomUpper oMenu;
    
    // Título
    private DomText aTitulo;
    private DomText oTitulo;
    
    // Descrição
    private DomTextLong aDescricao;
    private DomTextLong oDescricao;
    
    // Sequência
    private DomInteger aSequencia;
    private DomInteger oSequencia;
    
    // Topo
    private DomFlag aTopo;
    private DomFlag oTopo;
    
    // Sistema (DEPRECIADO)
    private DomId aSistemaId;
    private DomId oSistemaId;
    
    // <editor-fold defaultstate="collapsed" desc="Atributo ID">
    
    public EntMenus id(Long value) {
        setId(value);
        return this;
    }
    
    public void setId(DomId value) {
        if (value == null || value.isNull()) {
            nullifyId();
        } else {
            aId.setValue(value.getValue());
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(String value) {
        if (value == null) {
            nullifyId();
        } else {
            aId.setValue(value);
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(Long value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void setId(Object value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyId() {
        if (!aId.isNull()) {
            aId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getId() {
        return aId;
    }
    
    public DomId oldId() {
        return oId;
    }
    
    public Long valueOfId() {
        return aId.getValue();
    }
    
    public boolean isIdModified() {
        return aId.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo MENU">
    
    public EntMenus menu(String value) {
        setMenu(value);
        return this;
    }
    
    public void setMenu(DomUpper value) {
        if (value == null || value.isNull()) {
            nullifyMenu();
        } else {
            aMenu.setValue(value.getValue());
            if (aMenu.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setMenu(String value) {
        if (value == null) {
            nullifyMenu();
        } else {
            aMenu.setValue(value);
            if (aMenu.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setMenu(Object value) {
        aMenu.setValue(value);
        if (aMenu.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyMenu() {
        if (!aMenu.isNull()) {
            aMenu.setNull(true);
            setModified(true);
        }
    }
    
    public DomUpper getMenu() {
        return aMenu;
    }
    
    public DomUpper oldMenu() {
        return oMenu;
    }
    
    public String valueOfMenu() {
        return aMenu.getValue();
    }
    
    public boolean isMenuModified() {
        return aMenu.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo TITULO">
    
    public EntMenus titulo(String value) {
        setTitulo(value);
        return this;
    }
    
    public void setTitulo(DomText value) {
        if (value == null || value.isNull()) {
            nullifyTitulo();
        } else {
            aTitulo.setValue(value.getValue());
            if (aTitulo.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setTitulo(String value) {
        if (value == null) {
            nullifyTitulo();
        } else {
            aTitulo.setValue(value);
            if (aTitulo.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setTitulo(Object value) {
        aTitulo.setValue(value);
        if (aTitulo.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyTitulo() {
        if (!aTitulo.isNull()) {
            aTitulo.setNull(true);
            setModified(true);
        }
    }
    
    public DomText getTitulo() {
        return aTitulo;
    }
    
    public DomText oldTitulo() {
        return oTitulo;
    }
    
    public String valueOfTitulo() {
        return aTitulo.getValue();
    }
    
    public boolean isTituloModified() {
        return aTitulo.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo DESCRICAO">
    
    public EntMenus descricao(String value) {
        setDescricao(value);
        return this;
    }
    
    public void setDescricao(DomTextLong value) {
        if (value == null || value.isNull()) {
            nullifyDescricao();
        } else {
            aDescricao.setValue(value.getValue());
            if (aDescricao.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setDescricao(String value) {
        if (value == null) {
            nullifyDescricao();
        } else {
            aDescricao.setValue(value);
            if (aDescricao.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setDescricao(Object value) {
        aDescricao.setValue(value);
        if (aDescricao.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyDescricao() {
        if (!aDescricao.isNull()) {
            aDescricao.setNull(true);
            setModified(true);
        }
    }
    
    public DomTextLong getDescricao() {
        return aDescricao;
    }
    
    public DomTextLong oldDescricao() {
        return oDescricao;
    }
    
    public String valueOfDescricao() {
        return aDescricao.getValue();
    }
    
    public boolean isDescricaoModified() {
        return aDescricao.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo SEQUENCIA">
    
    public EntMenus sequencia(Integer value) {
        setSequencia(value);
        return this;
    }
    
    public void setSequencia(DomInteger value) {
        if (value == null || value.isNull()) {
            nullifySequencia();
        } else {
            aSequencia.setValue(value.getValue());
            if (aSequencia.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setSequencia(String value) {
        if (value == null) {
            nullifySequencia();
        } else {
            aSequencia.setValue(value);
            if (aSequencia.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setSequencia(Integer value) {
        aSequencia.setValue(value);
        if (aSequencia.isModified()) {
            setModified(true);
        }
    }
    
    public void setSequencia(Object value) {
        aSequencia.setValue(value);
        if (aSequencia.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifySequencia() {
        if (!aSequencia.isNull()) {
            aSequencia.setNull(true);
            setModified(true);
        }
    }
    
    public DomInteger getSequencia() {
        return aSequencia;
    }
    
    public DomInteger oldSequencia() {
        return oSequencia;
    }
    
    public Integer valueOfSequencia() {
        return aSequencia.getValue();
    }
    
    public boolean isSequenciaModified() {
        return aSequencia.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo TOPO">
    
    public EntMenus topo(String value) {
        setTopo(value);
        return this;
    }
    
    public void setTopo(DomFlag value) {
        if (value == null || value.isNull()) {
            nullifyTopo();
        } else {
            aTopo.setValue(value.getValue());
            if (aTopo.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setTopo(String value) {
        if (value == null) {
            nullifyTopo();
        } else {
            aTopo.setValue(value);
            if (aTopo.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setTopo(Object value) {
        aTopo.setValue(value);
        if (aTopo.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyTopo() {
        if (!aTopo.isNull()) {
            aTopo.setNull(true);
            setModified(true);
        }
    }
    
    public DomFlag getTopo() {
        return aTopo;
    }
    
    public DomFlag oldTopo() {
        return oTopo;
    }
    
    public String valueOfTopo() {
        return aTopo.getValue();
    }
    
    public boolean isTopoModified() {
        return aTopo.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo SISTEMA_ID">
    
    public EntMenus sistemaId(Long value) {
        setSistemaId(value);
        return this;
    }
    
    public void setSistemaId(DomId value) {
        if (value == null || value.isNull()) {
            nullifySistemaId();
        } else {
            aSistemaId.setValue(value.getValue());
            if (aSistemaId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setSistemaId(String value) {
        if (value == null) {
            nullifySistemaId();
        } else {
            aSistemaId.setValue(value);
            if (aSistemaId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setSistemaId(Long value) {
        aSistemaId.setValue(value);
        if (aSistemaId.isModified()) {
            setModified(true);
        }
    }
    
    public void setSistemaId(Object value) {
        aSistemaId.setValue(value);
        if (aSistemaId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifySistemaId() {
        if (!aSistemaId.isNull()) {
            aSistemaId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getSistemaId() {
        return aSistemaId;
    }
    
    public DomId oldSistemaId() {
        return oSistemaId;
    }
    
    public Long valueOfSistemaId() {
        return aSistemaId.getValue();
    }
    
    public boolean isSistemaIdModified() {
        return aSistemaId.isModified();
    }
    // </editor-fold>
    // </editor-fold>
    
    @Override
    protected void processDeleteRestrict() throws AdsException {
        // Nullify cascade RTMENU.ITENS_MENUS.FK_SUB_MENU
        {
            EntItensMenus external = new EntItensMenus(ctx);
            external.findBySubMenu(valueOfId());
            if (external.next()) {
                throw new AdsException("RTMENU.ITENS_MENUS.FK_SUB_MENU.RESTRICTED",
                        AdsException.ERROR,
                        "Não pode excluir porque existem Itens de menus fazendo referencia para este registro");
            }
            external.close();
        }
    }
    
    @Override
    protected void processDeleteCascade() throws AdsException {
        // Delete cascade RTMENU.ITENS_MENUS.FK_MENU
        {
            EntItensMenus itensMenus = new EntItensMenus(ctx);
            itensMenus.del("select id from ITENS_MENUS where MENU_ID = " + valueOfId());
        }
    }
    
    // <editor-fold defaultstate="collapsed" desc="getErrors">
    /**
     * Traduz um erro recebido do banco de dados para um AdsException
     */
    @Override
    public AdsException getErrors(String errorMsg, int transaction) {
        AdsException e;
        String msg = errorMsg.toUpperCase();
        
        if (transaction == DELETE_TRANSACTION) {
            if (msg.indexOf("FK_SUB_MENU") >= 0) {
                e = new AdsException("RTMENU.ITENS_MENUS.FK_SUB_MENU.RESTRICTED", 
                        Severity.ERROR,
                        "Não pode excluir porque existem Itens de menus fazendo referencia para este registro! (FK_SUB_MENU)");
                return e;
            } else if (msg.indexOf("FK_MENU_USUARIO") >= 0) {
                e = new AdsException("RTAUTH_PESS.USUARIOS.FK_MENU_USUARIO.RESTRICTED", 
                        Severity.ERROR,
                        "Não pode excluir porque existem Usuários fazendo referencia para este registro! (FK_MENU_USUARIO)");
                return e;
            } else {
                e = new AdsException("RTMENU.MENUS.GET_ERRORS_UNKNOWN",
                        AdsException.UNKNOWN,
                        "Erro não esperado: " + errorMsg);
            }
        } else {
            if (msg.indexOf("PK_MENU") >= 0) {
                e = new AdsException("RTMENU.MENUS.PK_MENU", 
                        Severity.ERROR,
                        "ID duplicado! (PK_MENU)");
                return e;
            } else if (msg.indexOf("UK_MENU_MENU") >= 0) {
                e = new AdsException("RTMENU.MENUS.UK_MENU_MENU", 
                        Severity.ERROR,
                        "Registro duplicado! Já existe um menu cadastrado com este nome global ou identificação! Menu ${MENU} (UK_MENU_MENU)");
                return e;
            } else {
                e = new AdsException("RTMENU.MENUS.GET_ERRORS_UNKNOWN",
                        AdsException.UNKNOWN,
                        "Erro não esperado: " + errorMsg);
            }
        }
        return e;
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Entity Information">
    
    public String getEntityName() {
        return ENTITY_NAME;
    }
    
    public String getTableName() {
        return TABLE_NAME;
    }
    
    public String idSequenceName() {
        return "PK_SEQUENCE";
    }
    
    private ArrayList<Field> allAttributes;
    public ArrayList<Field> getAllAttributes() {
        if (allAttributes == null) {
            allAttributes = new ArrayList<Field>();
            allAttributes.add(aId);
            allAttributes.add(aMenu);
            allAttributes.add(aTitulo);
            allAttributes.add(aDescricao);
            allAttributes.add(aSequencia);
            allAttributes.add(aTopo);
            allAttributes.add(aSistemaId);
        }
        return allAttributes;
    }
    
    /**
     * Retorna o valor da primeira UK da entidade
     * Se ela for composta, retorna a concatenação de toda a combinação
     * de atributos separados por um espaço.
     */
    public String valueOfUk() {
        return getMenu().toString();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Relationships">
    
    
    public void findByMenu(String menu) throws AdsException {
        findBy(new String[] {"MENU"},
                new Object[] {menu});
    }
    /**
     * Retorna os registros de ITENS_MENUS que referenciam este registro através do atributo SUB_MENU_ID
     */
    public EntItensMenus findAllItensMenusSubMenu() throws AdsException {
        return findAllItensMenusSubMenu("order by ID");
    }
    
    /**
     * Retorna os registros de ITENS_MENUS que referenciam este registro através do atributo SUB_MENU_ID
     */
    public EntItensMenus findAllItensMenusSubMenu(String sqlAppend) throws AdsException {
        EntItensMenus out = new EntItensMenus(ctx);
        out.find("select ID from ITENS_MENUS where SUB_MENU_ID = " + valueOfId() + " " + sqlAppend);
        return out;
    }
    
    /**
     * Retorna os registros de ITENS_MENUS que referenciam este registro através do atributo MENU_ID
     */
    public EntItensMenus findAllItensMenusMenu() throws AdsException {
        return findAllItensMenusMenu("order by ID");
    }
    
    /**
     * Retorna os registros de ITENS_MENUS que referenciam este registro através do atributo MENU_ID
     */
    public EntItensMenus findAllItensMenusMenu(String sqlAppend) throws AdsException {
        EntItensMenus out = new EntItensMenus(ctx);
        out.find("select ID from ITENS_MENUS where MENU_ID = " + valueOfId() + " " + sqlAppend);
        return out;
    }
    
    
    /**
     * Método que copia os valores dos atributos
     * para os valores respectivos old 
     */
    public void saveOldAtributes() {
        oId.setValue(aId);
        oTopo.setValue(aTopo);
        oMenu.setValue(aMenu);
        oDescricao.setValue(aDescricao);
        oTitulo.setValue(aTitulo);
        oSequencia.setValue(aSequencia);
        oSistemaId.setValue(aSistemaId);
    }
    
    /**
     * Método que retorna as regras da entidade
     * @return ArrayList com as regras ou null caso não existir nenhuma regra
     */
    public ArrayList getAllRules() {
        ArrayList<EntityRule> out = new ArrayList<EntityRule>();
        {
            UniqueKeyRule rule = new UniqueKeyRule();
            rule.setEntity(EntMenus.class);
            rule.setName("UK_MENU_MENU");
            rule.addAttribute(new DomUpper("MENU",""));
            out.add(rule);
        }
        {
            PrimaryKeyRule rule = new PrimaryKeyRule();
            rule.setEntity(EntMenus.class);
            rule.setName("PK_MENU");
            rule.setPkAttribute(new DomId("ID",""));
            out.add(rule);
        }
        return out;
    }
    // </editor-fold>
    
    @Override
    public void fillDefaultValues() throws AdsException {
        if (aId.isNull()) {
            aId.setValue("" + ctx.getNextVal("pk_sequence"));
        }
        if (getTopo().isNull()) {
            setTopo(getTopo().getDefaultValue());
        }
        if (getSequencia().isNull()) {
            setSequencia(getSequencia().getDefaultValue());
        }
    }
    
    // <editor-fold defaultstate="collapsed" desc="Métodos customizados">
    
    /**
     * Has menu.
     * <p>
     * Verifica se o menu tem um determinado sub-menu.
     * <P>
     * Esta função é utilizada para evitar que a estrutura de menus cause um 
     * loop infinito.
     * <P>
     * 
     * <P>
     * Algoritmo:
     * <P>
     *  if menuId == this.ID
     * <P>
     *      return true
     * <P>
     *  else
     * <P>
     *      for each menu in sub-menus loop
     * <P>
     *          if menu.hasMenu(menuId) 
     * <P>
     *              return true
     * <P>
     *          end-if
     * <P>
     *      end-loop
     * <P>
     *      return false
     * <P>
     *  end-if
     * <P>
     */
    public boolean hasMenu(long menuId) throws AdsException {
        // <user-code id="751576" parentId="751574" hashcode="-46b5542b" length="427">
        if (menuId == valueOfId()) {
            return true;
        } else {
            EntItensMenus item = new EntItensMenus(ctx);
            EntMenus submenu = item.joinSubMenu();
            item.filterBy().equal(item.getMenuId(), valueOfId());
            try {
                while (item.next()) {
                    if (submenu.isNotNull() 
                            && submenu.hasMenu(menuId)) return true;
                }
            } finally {
                item.close();
            }
        }
        return false;
        // </user-code>
    }
}
